<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  <title>Android-Binder技术之ServiceManager获取 | 清风向阳</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  
    <meta name="keywords" content="Joker,Joker's Blog" />
  
  <meta name="description" content="既然ServiceManager已经启动了，那么就可以被获取了，获取的方法是defaultServiceManager(),注意这个方法返回的并不是ServiceManager进程，而是一个用C写在底层的IServiceManager对象。那么服务端需要获取ServiceManager来注册对象，也就是通过操作IServiceManager对象进行的，同样客户端需要获取ServiceManage">
<meta name="keywords" content="Android,Binder,ServiceManager">
<meta property="og:type" content="article">
<meta property="og:title" content="Android-Binder技术之ServiceManager获取">
<meta property="og:url" content="http://mjjde.github.io/2017/04/26/Android-Binder技术之ServiceManager获取/index.html">
<meta property="og:site_name" content="清风向阳">
<meta property="og:description" content="既然ServiceManager已经启动了，那么就可以被获取了，获取的方法是defaultServiceManager(),注意这个方法返回的并不是ServiceManager进程，而是一个用C写在底层的IServiceManager对象。那么服务端需要获取ServiceManager来注册对象，也就是通过操作IServiceManager对象进行的，同样客户端需要获取ServiceManage">
<meta property="og:updated_time" content="2017-09-15T07:00:11.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Android-Binder技术之ServiceManager获取">
<meta name="twitter:description" content="既然ServiceManager已经启动了，那么就可以被获取了，获取的方法是defaultServiceManager(),注意这个方法返回的并不是ServiceManager进程，而是一个用C写在底层的IServiceManager对象。那么服务端需要获取ServiceManager来注册对象，也就是通过操作IServiceManager对象进行的，同样客户端需要获取ServiceManage">
  
  
    <link rel="icon" href="/favicon_pic.ico">
  
  <link href="//cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
  <link rel="stylesheet" href="/css/style.css">
  <script src="/js/pace.min.js"></script>
  

  
  

</head>

<body>
  <div id="container">
      <header id="header">
    <div id="banner"></div>
    <div id="header-outer">
        <div id="header-menu" class="header-menu-pos animated">
            <div class="header-menu-container">
                <a href="/" class="left">
                    <span class="site-title">Joker&#39;s Blog</span>
                </a>
                <nav id="header-menu-nav" class="right">
                    
                    <a  href="/">
                        <i class="fa fa-home"></i>
                        <span>Home</span>
                    </a>
                    
                    <a  href="/archives">
                        <i class="fa fa-archive"></i>
                        <span>Archives</span>
                    </a>
                    
                    <a  href="/about">
                        <i class="fa fa-user"></i>
                        <span>About</span>
                    </a>
                    
                </nav>
                <a class="mobile-header-menu-button">
                    <i class="fa fa-bars"></i>
                </a>
            </div>
        </div>
        <div id="header-row">
            <div id="logo">
                <a href="/">
                    <img src="/images/avatar.jpg" alt="logo">
                </a>
            </div>
            <div class="header-info">
                <div id="header-title">
                    
                    <h2>
                        Joker&#39;s Blog
                    </h2>
                    
                </div>
                <div id="header-description">
                    
                    <h3>
                        一个认真的技术博客
                    </h3>
                    
                </div>
            </div>
            <nav class="header-nav">
                <div class="social">
                    
                        <a title="Joker"  href="//joker-studio.pub">
                            <i class="fa fa-home fa-2x"></i></a>
                    
                        <a title="Github" target="_blank" href="//github.com/mjjde">
                            <i class="fa fa-github fa-2x"></i></a>
                    
                </div>
            </nav>
        </div>
    </div>
</header>
      <div class="outer">
        <section id="main" class="body-wrap"><article id="post-Android-Binder技术之ServiceManager获取" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 class="post-title" itemprop="name">
      Android-Binder技术之ServiceManager获取
    </h1>
    <div class="post-title-bar">
      <ul>
          
              <li>
                  <i class="fa fa-book"></i>
                  
                      <a href="/categories/Android技术/">Android技术</a>
                  
              </li>
          
        <li>
          <i class="fa fa-calendar"></i>  2017-04-26
        </li>
        <li>
          <i class="fa fa-eye"></i>
          <span id="busuanzi_value_page_pv"></span>
        </li>
      </ul>
    </div>
  

          
      </header>
    
    <div class="article-entry post-content" itemprop="articleBody">
      
            
            <blockquote>
<p>既然ServiceManager已经启动了，那么就可以被获取了，获取的方法是defaultServiceManager(),注意这个方法返回的并不是ServiceManager进程，而是一个用C写在底层的IServiceManager对象。那么服务端需要获取ServiceManager来注册对象，也就是通过操作IServiceManager对象进行的，同样客户端需要获取ServiceManager注册过的Service，也是通过操作IServiceManager来进行的。接下来我们就来分析一下defaultServiceManager()方法。<br><a id="more"></a></p>
</blockquote>
<h2 id="一-获取过程"><a href="#一-获取过程" class="headerlink" title="一.获取过程"></a>一.获取过程</h2><p>获取ServiceManager的方法是defaultServiceManager,我们来看下源码。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line">sp&lt;IServiceManager&gt; defaultServiceManager()</div><div class="line">&#123;</div><div class="line">    <span class="keyword">if</span> (gDefaultServiceManager != <span class="keyword">NULL</span>) <span class="keyword">return</span> gDefaultServiceManager;</div><div class="line"></div><div class="line">    &#123;</div><div class="line">        AutoMutex _l(gDefaultServiceManagerLock);</div><div class="line">        <span class="keyword">while</span> (gDefaultServiceManager == <span class="keyword">NULL</span>) &#123;</div><div class="line">            gDefaultServiceManager = interface_cast&lt;IServiceManager&gt;(</div><div class="line">                ProcessState::self()-&gt;getContextObject(<span class="keyword">NULL</span>));</div><div class="line">            <span class="keyword">if</span> (gDefaultServiceManager == <span class="keyword">NULL</span>)</div><div class="line">                sleep(<span class="number">1</span>);</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="keyword">return</span> gDefaultServiceManager;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>这个方法就像我们上面说的一样，返回的是一个IServiceManager对象。这个对象采用的是单例模式，第一次创建之后的获取都是直接返回。</p>
<h3 id="ProcessState-self"><a href="#ProcessState-self" class="headerlink" title="ProcessState::self()"></a>ProcessState::self()</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">sp&lt;ProcessState&gt; ProcessState::self()</div><div class="line">&#123;</div><div class="line">    Mutex::Autolock _l(gProcessMutex);</div><div class="line">    <span class="keyword">if</span> (gProcess != <span class="literal">NULL</span>) &#123;</div><div class="line">        <span class="keyword">return</span> gProcess;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="comment">//实例化ProcessState 【见小节2.2】</span></div><div class="line">    gProcess = <span class="keyword">new</span> ProcessState;</div><div class="line">    <span class="keyword">return</span> gProcess;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>这个方法返回的是个ProcessState对象，我们看到这个依然是个单例模式。</p>
<h4 id="ProcessState初始化"><a href="#ProcessState初始化" class="headerlink" title="ProcessState初始化"></a>ProcessState初始化</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line">ProcessState::ProcessState()</div><div class="line">    : mDriverFD(open_driver()) <span class="comment">// 打开Binder驱动</span></div><div class="line">    , mVMStart(MAP_FAILED)</div><div class="line">    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)</div><div class="line">    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)</div><div class="line">    , mExecutingThreadsCount(<span class="number">0</span>)</div><div class="line">    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)</div><div class="line">    , mManagesContexts(<span class="literal">false</span>)</div><div class="line">    , mBinderContextCheckFunc(<span class="literal">NULL</span>)</div><div class="line">    , mBinderContextUserData(<span class="literal">NULL</span>)</div><div class="line">    , mThreadPoolStarted(<span class="literal">false</span>)</div><div class="line">    , mThreadPoolSeq(<span class="number">1</span>)</div><div class="line">&#123;</div><div class="line">    <span class="keyword">if</span> (mDriverFD &gt;= <span class="number">0</span>) &#123;</div><div class="line">        <span class="comment">//采用内存映射函数mmap，给binder分配一块虚拟地址空间,用来接收事务</span></div><div class="line">        mVMStart = mmap(<span class="number">0</span>, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, <span class="number">0</span>);</div><div class="line">        <span class="keyword">if</span> (mVMStart == MAP_FAILED) &#123;</div><div class="line">            close(mDriverFD); <span class="comment">//没有足够空间分配给/dev/binder,则关闭驱动</span></div><div class="line">            mDriverFD = <span class="number">-1</span>;</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<ol>
<li>打开binder驱动获取文件句柄赋值给mDriverFD</li>
<li>调用mmap创建内存映射空间</li>
</ol>
<h4 id="ProcessState-open-driver"><a href="#ProcessState-open-driver" class="headerlink" title="ProcessState::open_driver()"></a>ProcessState::open_driver()</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">open_driver</span><span class="params">()</span></span></div><div class="line">&#123;</div><div class="line">    <span class="comment">// 打开/dev/binder设备，建立与内核的Binder驱动的交互通道</span></div><div class="line">    <span class="keyword">int</span> fd = open(<span class="string">"/dev/binder"</span>, O_RDWR);</div><div class="line">    <span class="keyword">if</span> (fd &gt;= <span class="number">0</span>) &#123;</div><div class="line">        fcntl(fd, F_SETFD, FD_CLOEXEC);</div><div class="line">        <span class="keyword">int</span> vers = <span class="number">0</span>;</div><div class="line">        <span class="keyword">status_t</span> result = ioctl(fd, BINDER_VERSION, &amp;vers);</div><div class="line">        <span class="keyword">if</span> (result == <span class="number">-1</span>) &#123;</div><div class="line">            close(fd);</div><div class="line">            fd = <span class="number">-1</span>;</div><div class="line">        &#125;</div><div class="line">        <span class="keyword">if</span> (result != <span class="number">0</span> || vers != BINDER_CURRENT_PROTOCOL_VERSION) &#123;</div><div class="line">            close(fd);</div><div class="line">            fd = <span class="number">-1</span>;</div><div class="line">        &#125;</div><div class="line">        <span class="keyword">size_t</span> maxThreads = DEFAULT_MAX_BINDER_THREADS;</div><div class="line"></div><div class="line">        <span class="comment">// 通过ioctl设置binder驱动，能支持的最大线程数</span></div><div class="line">        result = ioctl(fd, BINDER_SET_MAX_THREADS, &amp;maxThreads);</div><div class="line">        <span class="keyword">if</span> (result == <span class="number">-1</span>) &#123;</div><div class="line">            ALOGE(<span class="string">"Binder ioctl to set max threads failed: %s"</span>, strerror(errno));</div><div class="line">        &#125;</div><div class="line">    &#125; <span class="keyword">else</span> &#123;</div><div class="line">        ALOGW(<span class="string">"Opening '/dev/binder' failed: %s\n"</span>, strerror(errno));</div><div class="line">    &#125;</div><div class="line">    <span class="keyword">return</span> fd;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<ol>
<li>调用binder_open函数打开binder驱动，这个我们在上篇文章已经介绍过了。</li>
<li>检查binder驱动版本号</li>
<li>调用binder_ioctl设置该进程的最大线程数<br>我们这里调用的open(“/dev/binder”, O_RDWR)和上篇文章介绍的不是同一个，上面文章是在ServiceManager进程里打开的驱动文件，而这次是调用defaultServiceManager进程里调用的。</li>
</ol>
<h4 id="ioctl-fd-BINDER-SET-MAX-THREADS-amp-maxThreads"><a href="#ioctl-fd-BINDER-SET-MAX-THREADS-amp-maxThreads" class="headerlink" title="ioctl(fd, BINDER_SET_MAX_THREADS, &amp;maxThreads)"></a>ioctl(fd, BINDER_SET_MAX_THREADS, &amp;maxThreads)</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">long</span> <span class="title">binder_ioctl</span><span class="params">(struct file *filp, <span class="keyword">unsigned</span> <span class="keyword">int</span> cmd, <span class="keyword">unsigned</span> <span class="keyword">long</span> arg)</span></span></div><div class="line">&#123;</div><div class="line"><span class="keyword">int</span> ret;</div><div class="line"><span class="class"><span class="keyword">struct</span> <span class="title">binder_proc</span> *<span class="title">proc</span> = <span class="title">filp</span>-&gt;<span class="title">private_data</span>;</span></div><div class="line"><span class="class"><span class="keyword">struct</span> <span class="title">binder_thread</span> *<span class="title">thread</span>;</span></div><div class="line"><span class="keyword">unsigned</span> <span class="keyword">int</span> size = _IOC_SIZE(cmd);</div><div class="line"><span class="keyword">void</span> __user *ubuf = (<span class="keyword">void</span> __user *)arg;</div><div class="line"></div><div class="line">ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error &lt; <span class="number">2</span>);</div><div class="line"></div><div class="line"><span class="comment">// 在proc进程中查找该线程对应的binder_thread；若查找失败，则新建一个binder_thread，并添加到proc-&gt;threads中。</span></div><div class="line">thread = binder_get_thread(proc);</div><div class="line">...</div><div class="line"></div><div class="line"><span class="keyword">switch</span> (cmd) &#123;</div><div class="line">    <span class="keyword">case</span> BINDER_SET_MAX_THREADS:</div><div class="line">        <span class="keyword">if</span> (copy_from_user(&amp;proc-&gt;max_threads, ubuf, <span class="keyword">sizeof</span>(proc-&gt;max_threads))) &#123;</div><div class="line">            ret = -EINVAL;</div><div class="line">            <span class="keyword">goto</span> err;</div><div class="line">        &#125;</div><div class="line">        <span class="keyword">break</span>;</div><div class="line"></div><div class="line">...</div><div class="line">&#125;</div><div class="line">ret = <span class="number">0</span>;</div><div class="line"></div><div class="line">...</div><div class="line"><span class="keyword">return</span> ret;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>就是将最大线程数目从用户空间拷贝到内核空间，进而赋值给binder_proc-&gt;max_threads。</p>
<h4 id="mmap"><a href="#mmap" class="headerlink" title="mmap"></a>mmap</h4><p>这个知识点我们已经在上篇文章介绍过，这里就不去介绍了。</p>
<p>到此我们已经分析完ProcessState::self()方法，这个方法主要是打开驱动文件，并且设置当前进程的最大线程数。</p>
<h3 id="ProcessState-getContextObject"><a href="#ProcessState-getContextObject" class="headerlink" title="ProcessState::getContextObject()"></a>ProcessState::getContextObject()</h3><p>sp <ibinder>ProcessState::getContextObject(const sp<ibinder>&amp; caller)<br>{<br>return getStrongProxyForHandle(0);<br>}<br>这里的0带表的是ServiceManager的句柄</ibinder></ibinder></p>
<h4 id="ProcessState-getStrongProxyForHandle"><a href="#ProcessState-getStrongProxyForHandle" class="headerlink" title="ProcessState::getStrongProxyForHandle()"></a>ProcessState::getStrongProxyForHandle()</h4><figure class="highlight lasso"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line">sp&lt;IBinder&gt; ProcessState<span class="type">::getStrongProxyForHandle</span>(int32_t <span class="keyword">handle</span>)</div><div class="line">&#123;</div><div class="line">    sp&lt;IBinder&gt; result;</div><div class="line"></div><div class="line">    AutoMutex _l(mLock);</div><div class="line"></div><div class="line">    <span class="comment">// 在矢量数组mHandleToObject中查找"句柄值为handle的handle_entry对象"；</span></div><div class="line">    <span class="comment">// 找到的话，则直接返回；找不到的话，则新建handle对应的handle_entry，并将其添加到mHandleToObject中。</span></div><div class="line">    handle_entry* e = lookupHandleLocked(<span class="keyword">handle</span>);</div><div class="line"></div><div class="line">    <span class="keyword">if</span> (e != <span class="built_in">NULL</span>) &#123;</div><div class="line">        IBinder* b = e-&gt;binder;</div><div class="line">        <span class="keyword">if</span> (b == <span class="built_in">NULL</span> || !e-&gt;refs-&gt;attemptIncWeak(this)) &#123;</div><div class="line">            <span class="comment">// 当handle==0(即是Service Manager的句柄)时，尝试去ping Binder驱动。</span></div><div class="line">            <span class="keyword">if</span> (<span class="keyword">handle</span> == <span class="number">0</span>) &#123;</div><div class="line">                Parcel <span class="built_in">data</span>;</div><div class="line">                status_t status = IPCThreadState<span class="type">::self</span>()-&gt;transact(</div><div class="line">                        <span class="number">0</span>, IBinder<span class="type">::PING_TRANSACTION</span>, <span class="built_in">data</span>, <span class="built_in">NULL</span>, <span class="number">0</span>);</div><div class="line">                <span class="keyword">if</span> (status == DEAD_OBJECT)</div><div class="line">                <span class="keyword">return</span> <span class="built_in">NULL</span>;</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            <span class="comment">// 新建BpBinder代理</span></div><div class="line">            b = <span class="literal">new</span> BpBinder(<span class="keyword">handle</span>);</div><div class="line">            e-&gt;binder = b;</div><div class="line">            <span class="keyword">if</span> (b) e-&gt;refs = b-&gt;getWeakRefs();</div><div class="line">            result = b;</div><div class="line">        &#125; <span class="keyword">else</span> &#123;</div><div class="line">            <span class="params">...</span></div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="keyword">return</span> result;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>getStrongProxyForHandle()的目的是返回句柄为handle的IBinder代理，这里是返回Service Manager的IBinder代理，IBinder中存有remoteBinder()和localBinder()</p>
<h4 id="ProcessState-lookupHandleLocked"><a href="#ProcessState-lookupHandleLocked" class="headerlink" title="ProcessState::lookupHandleLocked()"></a>ProcessState::lookupHandleLocked()</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">ProcessState::handle_entry* ProcessState::lookupHandleLocked(<span class="keyword">int32_t</span> handle)</div><div class="line">&#123;               </div><div class="line">    <span class="keyword">const</span> <span class="keyword">size_t</span> N=mHandleToObject.size();</div><div class="line">    <span class="keyword">if</span> (N &lt;= (<span class="keyword">size_t</span>)handle) &#123;</div><div class="line">        handle_entry e;</div><div class="line">        e.binder = <span class="literal">NULL</span>;</div><div class="line">        e.refs = <span class="literal">NULL</span>;</div><div class="line">        <span class="keyword">status_t</span> err = mHandleToObject.insertAt(e, N, handle+<span class="number">1</span>-N);</div><div class="line">        <span class="keyword">if</span> (err &lt; NO_ERROR) <span class="keyword">return</span> <span class="literal">NULL</span>;</div><div class="line">    &#125;   </div><div class="line">    <span class="keyword">return</span> &amp;mHandleToObject.editItemAt(handle);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<ol>
<li><p>mHandleToObject是Vector矢量数组，这个方法首先在 mHandleToObject中查找handle的handle_entry，如果存在的话就直接返回，如果不存在，那么就创建一个handle_entry存放在mHandleToObject，这个主要起到一个缓存的作用，不需要每次都去通信。</p>
</li>
<li><p>很显然，此时e!=NULL为true，进入if(e!=NULL)中。而此时e-&gt;binder=NULL，并且handle=0；则调用IPCThreadState::self()-&gt;transact()尝试去和Binder驱动通信(尝试去ping内核中Binder驱动)。由于Binder驱动已启动，ping通信是能够成功的。</p>
</li>
<li><p>接着创建了一个BpBinder对象，并将该对象赋值给了handle_entry的b变量。</p>
</li>
</ol>
<h4 id="BpBinder-BpBinder"><a href="#BpBinder-BpBinder" class="headerlink" title="BpBinder::BpBinder"></a>BpBinder::BpBinder</h4><figure class="highlight lasso"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">BpBinder<span class="type">::BpBinder</span>(int32_t <span class="keyword">handle</span>)</div><div class="line">    : mHandle(<span class="keyword">handle</span>)</div><div class="line">    , mAlive(<span class="number">1</span>)</div><div class="line">    , mObitsSent(<span class="number">0</span>)</div><div class="line">    , mObituaries(<span class="built_in">NULL</span>)</div><div class="line">&#123;</div><div class="line">    ALOGV(<span class="string">"Creating BpBinder %p handle %d\n"</span>, this, mHandle);</div><div class="line"></div><div class="line">    extendObjectLifetime(OBJECT_LIFETIME_WEAK);</div><div class="line">    IPCThreadState<span class="type">::self</span>()-&gt;incWeakHandle(<span class="keyword">handle</span>);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>创建BpBinder对象中会将handle相对应Binder的弱引用增加1.</p>
<h4 id="IPCThreadState-self"><a href="#IPCThreadState-self" class="headerlink" title="IPCThreadState::self()"></a>IPCThreadState::self()</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">static</span> <span class="keyword">pthread_mutex_t</span> gTLSMutex = PTHREAD_MUTEX_INITIALIZER;</div><div class="line"><span class="keyword">static</span> <span class="keyword">bool</span> gHaveTLS = <span class="literal">false</span>;</div><div class="line"><span class="keyword">static</span> <span class="keyword">pthread_key_t</span> gTLS = <span class="number">0</span>;</div><div class="line"><span class="keyword">static</span> <span class="keyword">bool</span> gShutdown = <span class="literal">false</span>;</div><div class="line"><span class="keyword">static</span> <span class="keyword">bool</span> gDisableBackgroundScheduling = <span class="literal">false</span>;</div><div class="line"></div><div class="line">IPCThreadState* IPCThreadState::self()</div><div class="line">&#123;</div><div class="line">    <span class="keyword">if</span> (gHaveTLS) &#123;</div><div class="line">restart:</div><div class="line">        <span class="keyword">const</span> <span class="keyword">pthread_key_t</span> k = gTLS;</div><div class="line">        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);</div><div class="line">        <span class="keyword">if</span> (st) <span class="keyword">return</span> st;</div><div class="line">        <span class="keyword">return</span> <span class="keyword">new</span> IPCThreadState;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="keyword">if</span> (gShutdown) <span class="keyword">return</span> <span class="literal">NULL</span>;</div><div class="line"></div><div class="line">    pthread_mutex_lock(&amp;gTLSMutex);</div><div class="line">    <span class="keyword">if</span> (!gHaveTLS) &#123;</div><div class="line">        <span class="keyword">if</span> (pthread_key_create(&amp;gTLS, threadDestructor) != <span class="number">0</span>) &#123;</div><div class="line">            pthread_mutex_unlock(&amp;gTLSMutex);</div><div class="line">            <span class="keyword">return</span> <span class="literal">NULL</span>;</div><div class="line">        &#125;</div><div class="line">        gHaveTLS = <span class="literal">true</span>;</div><div class="line">    &#125;</div><div class="line">    pthread_mutex_unlock(&amp;gTLSMutex);</div><div class="line">    <span class="keyword">goto</span> restart;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>self()的源码比较简单，它的作用是获取IPCThreadState对象。若该对象已经存在，则直接返回；否则，新建IPCThreadState对象</p>
<h4 id="IPCThreadState-IPCThreadState"><a href="#IPCThreadState-IPCThreadState" class="headerlink" title="IPCThreadState::IPCThreadState()"></a>IPCThreadState::IPCThreadState()</h4><figure class="highlight less"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="attribute">IPCThreadState</span>::IPCThreadState()</div><div class="line">    : mProcess(<span class="attribute">ProcessState</span>::self()),</div><div class="line">    mMyThreadId(androidGetTid()),</div><div class="line">    mStrictModePolicy(<span class="number">0</span>),</div><div class="line">    mLastTransactionBinderFlags(<span class="number">0</span>)</div><div class="line">&#123;</div><div class="line">    pthread_setspecific(gTLS, this);</div><div class="line">    <span class="selector-tag">clearCaller</span>();</div><div class="line">    <span class="selector-tag">mIn</span><span class="selector-class">.setDataCapacity</span>(<span class="number">256</span>);</div><div class="line">    <span class="selector-tag">mOut</span><span class="selector-class">.setDataCapacity</span>(<span class="number">256</span>);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<ol>
<li>将ProcessState对象赋值给成员变量mProcess</li>
<li>IPCThreadState是与Binder驱动交互的类，那么mIn则表示将要发送给Binder驱动的内容，mOut表示Binder驱动返回的内容</li>
</ol>
<p>到这里ProcessState::getContextObject()就结束了。我们可以简化代码<br>gDefaultServiceManager = interface_cast<iservicemanager>(new BpBinder(0));</iservicemanager></p>
<h3 id="interface-cast"><a href="#interface-cast" class="headerlink" title="interface_cast()"></a>interface_cast()</h3><figure class="highlight monkey"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">template&lt;typename <span class="class"><span class="keyword">INTERFACE</span>&gt;</span></div><div class="line"><span class="keyword">inline</span> sp&lt;<span class="class"><span class="keyword">INTERFACE</span>&gt; <span class="title">interface_cast</span>(<span class="title">const</span> <span class="title">sp</span>&lt;<span class="title">IBinder</span>&gt;&amp; <span class="title">obj</span>)</span></div><div class="line">&#123;</div><div class="line">    <span class="keyword">return</span> <span class="class"><span class="keyword">INTERFACE</span>::<span class="title">asInterface</span>(<span class="title">obj</span>);</span></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>这里的INTERFACE是IServiceManager那么最后返回的是IServiceManager::asInterface(obj)</p>
<h3 id="IServiceManager-asInterface"><a href="#IServiceManager-asInterface" class="headerlink" title="IServiceManager::asInterface()"></a>IServiceManager::asInterface()</h3><p>对于asInterface()函数，通过搜索代码，你会发现根本找不到这个方法是在哪里定义这个函数的, 其实是通过模板函数来定义的，通过下面两个代码完成的：</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//位于IServiceManager.h文件</span></div><div class="line"><span class="function"><span class="title">DECLARE_META_INTERFACE</span><span class="params">(ServiceManager)</span></span></div><div class="line"><span class="comment">//位于IServiceManager.cpp文件</span></div><div class="line"><span class="function"><span class="title">IMPLEMENT_META_INTERFACE</span><span class="params">(ServiceManager,<span class="string">"android.os.IServiceManager"</span>)</span></span></div></pre></td></tr></table></figure>
<h4 id="DECLARE-META-INTERFACE"><a href="#DECLARE-META-INTERFACE" class="headerlink" title="DECLARE_META_INTERFACE"></a>DECLARE_META_INTERFACE</h4><figure class="highlight elixir"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#define DECLARE_META_INTERFACE(INTERFACE)                               \</span></div><div class="line">    static const <span class="symbol">android:</span><span class="symbol">:String16</span> descriptor;                          \</div><div class="line">    static <span class="symbol">android:</span><span class="symbol">:sp&lt;I</span><span class="comment">##INTERFACE&gt; asInterface(                       \</span></div><div class="line">            const <span class="symbol">android:</span><span class="symbol">:sp&lt;android</span><span class="symbol">:</span><span class="symbol">:IBinder&gt;&amp;</span> obj);                  \</div><div class="line">    virtual const <span class="symbol">android:</span><span class="symbol">:String16&amp;</span> getInterfaceDescriptor() const;    \</div><div class="line">    I<span class="comment">##INTERFACE();                                                     \</span></div><div class="line">    virtual ~I<span class="comment">##INTERFACE();                                            \</span></div></pre></td></tr></table></figure>
<p>INTERFACE=ServiceManager展开即可得：</p>
<figure class="highlight rust"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> android::String16 descriptor;</div><div class="line"></div><div class="line"><span class="keyword">static</span> android::sp&lt; IServiceManager &gt; asInterface(<span class="keyword">const</span> android::sp&lt;android::IBinder&gt;&amp; obj)</div><div class="line"></div><div class="line"><span class="keyword">virtual</span> <span class="keyword">const</span> android::String16&amp; getInterfaceDescriptor() <span class="keyword">const</span>;</div><div class="line"></div><div class="line">IServiceManager ();</div><div class="line"><span class="keyword">virtual</span> ~IServiceManager();</div></pre></td></tr></table></figure>
<h4 id="IMPLEMENT-META-INTERFACE"><a href="#IMPLEMENT-META-INTERFACE" class="headerlink" title="IMPLEMENT_META_INTERFACE"></a>IMPLEMENT_META_INTERFACE</h4><figure class="highlight clean"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line">#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \</div><div class="line">    const android::String16 I##INTERFACE::descriptor(NAME);             \</div><div class="line">    const android::String16&amp;                                            \</div><div class="line">            I##INTERFACE::getInterfaceDescriptor() const &#123;              \</div><div class="line">        return I##INTERFACE::descriptor;                                \</div><div class="line">    &#125;                                                                   \</div><div class="line">    android::sp&lt;I##INTERFACE&gt; I##INTERFACE::asInterface(                \</div><div class="line">            const android::sp&lt;android::IBinder&gt;&amp; obj)                   \</div><div class="line">    &#123;                                                                   \</div><div class="line">        android::sp&lt;I##INTERFACE&gt; intr;                                 \</div><div class="line">        <span class="keyword">if</span> (obj != NULL) &#123;                                              \</div><div class="line">            intr = static_cast&lt;I##INTERFACE*&gt;(                          \</div><div class="line">                obj-&gt;queryLocalInterface(                               \</div><div class="line">                        I##INTERFACE::descriptor).get());               \</div><div class="line">            <span class="keyword">if</span> (intr == NULL) &#123;                                         \</div><div class="line">                intr = new Bp##INTERFACE(obj);                          \</div><div class="line">            &#125;                                                           \</div><div class="line">        &#125;                                                               \</div><div class="line">        return intr;                                                    \</div><div class="line">    &#125;                                                                   \</div><div class="line">    I##INTERFACE::I##INTERFACE() &#123; &#125;                                    \</div><div class="line">    I##INTERFACE::~I##INTERFACE() &#123; &#125;                                   \</div></pre></td></tr></table></figure>
<p>INTERFACE=ServiceManager, NAME=”android.os.IServiceManager”展开即可得：<br>const android::String16 IServiceManager::descriptor(“android.os.IServiceManager”);</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> android::String16&amp; IServiceManager::getInterfaceDescriptor() <span class="keyword">const</span></div><div class="line">&#123;</div><div class="line">    <span class="keyword">return</span> IServiceManager::descriptor;</div><div class="line">&#125;</div><div class="line"></div><div class="line">android::sp&lt;IServiceManager&gt; IServiceManager::asInterface(<span class="keyword">const</span> android::sp&lt;android::IBinder&gt;&amp; obj)</div><div class="line">&#123;</div><div class="line">    android::sp&lt;IServiceManager&gt; intr;</div><div class="line">        <span class="keyword">if</span>(obj != <span class="literal">NULL</span>) &#123;</div><div class="line">        intr = <span class="keyword">static_cast</span>&lt;IServiceManager *&gt;(</div><div class="line">            obj-&gt;queryLocalInterface(IServiceManager::descriptor).get());</div><div class="line">        <span class="keyword">if</span> (intr == <span class="literal">NULL</span>) &#123;</div><div class="line">            intr = <span class="keyword">new</span> BpServiceManager(obj);  </div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line">    <span class="keyword">return</span> intr;</div><div class="line">&#125;</div><div class="line"></div><div class="line">IServiceManager::IServiceManager () &#123; &#125;</div><div class="line">IServiceManager::~ IServiceManager() &#123; &#125;</div></pre></td></tr></table></figure>
<p>我们看到了IServiceManager::asInterface方法的实现，new BpServiceManager(obj)</p>
<ol>
<li>obj是传入的BpBinder对象，不为NULL。因此，执行obj-&gt;queryLocalInterface(“android.os.IServiceManager”)来查找名称为”android.os.IServiceManager”的本地接口，queryLocalInterface()的实现在BpBinder的父类IBinder中，具体在文件frameworks/native/libs/binder/Binder.cpp中。很显然，IServiceManager接口还没创建，因此intr=NULL。</li>
<li>新建BpServiceManager(obj)对象，并返回。</li>
</ol>
<p>到目前为止，gDefaultServiceManager的创建流程就分析完了，它实际返回的是一个BpServiceManager对象，该对象包含IBinder的代理BpBinder。以下是转换后的获取gDefaultServiceManager的语句</p>
<p>gDefaultServiceManager = new BpServiceManager(new BpBinder(0));</p>

            <div class="post-copyright">
    <div class="content">
        <p>最后更新： 2017年09月15日 15:00</p>
        <p>原始链接： <a class="post-url" href="/2017/04/26/Android-Binder技术之ServiceManager获取/" title="Android-Binder技术之ServiceManager获取">http://mjjde.github.io/2017/04/26/Android-Binder技术之ServiceManager获取/</a></p>
        <footer>
            <a href="http://mjjde.github.io">
                <img src="/images/avatar.jpg" alt="Joker Mei">
                Joker Mei
            </a>
        </footer>
    </div>
</div>

      
    </div>
    <footer class="article-footer">
        
        
<div class="post-share">
    <a href="javascript:;" id="share-sub" class="post-share-fab">
        <i class="fa fa-share-alt"></i>
    </a>
    <div class="post-share-list" id="share-list">
        <ul class="share-icons">
          <li>
            <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=http://mjjde.github.io/2017/04/26/Android-Binder技术之ServiceManager获取/&title=《Android-Binder技术之ServiceManager获取》 — 清风向阳&pic=http://mjjde.github.ioimages/avatar.jpg" data-title="微博">
              <i class="fa fa-weibo"></i>
            </a>
          </li>
          <li>
            <a class="weixin share-sns" id="wxFab" href="javascript:;" data-title="微信">
              <i class="fa fa-weixin"></i>
            </a>
          </li>
          <li>
            <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://mjjde.github.io/2017/04/26/Android-Binder技术之ServiceManager获取/&title=《Android-Binder技术之ServiceManager获取》 — 清风向阳&source=
既然ServiceManager已经启动了，那么就可以被获取了，获取的方法是defaultServiceManager(),注意这个方法返回的并不是Se..." data-title="QQ">
              <i class="fa fa-qq"></i>
            </a>
          </li>
          <li>
            <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=http://mjjde.github.io/2017/04/26/Android-Binder技术之ServiceManager获取/" data-title="Facebook">
              <i class="fa fa-facebook"></i>
            </a>
          </li>
          <li>
            <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《Android-Binder技术之ServiceManager获取》 — 清风向阳&url=http://mjjde.github.io/2017/04/26/Android-Binder技术之ServiceManager获取/&via=http://mjjde.github.io" data-title="Twitter">
              <i class="fa fa-twitter"></i>
            </a>
          </li>
          <li>
            <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=http://mjjde.github.io/2017/04/26/Android-Binder技术之ServiceManager获取/" data-title="Google+">
              <i class="fa fa-google-plus"></i>
            </a>
          </li>
        </ul>
     </div>
</div>
<div class="post-modal wx-share" id="wxShare">
    <a class="close" href="javascript:;" id="wxShare-close">×</a>
    <p>扫一扫，分享到微信</p>
    <img src="//api.qrserver.com/v1/create-qr-code/?data=http://mjjde.github.io/2017/04/26/Android-Binder技术之ServiceManager获取/" alt="微信分享二维码">
</div>

<div class="mask"></div>

        
        <ul class="article-footer-menu">
            
            
  <li class="article-footer-tags">
    <i class="fa fa-tags"></i>
      
    <a href="/tags/Android/" class="color3">Android</a>
      
    <a href="/tags/Binder/" class="color2">Binder</a>
      
    <a href="/tags/ServiceManager/" class="color5">ServiceManager</a>
      
  </li>

        </ul>
        
    </footer>
  </div>
</article>


    <aside class="post-toc-pos post-toc-top" id="post-toc">
        <nav class="post-toc-wrap">
            <ol class="post-toc"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#一-获取过程"><span class="post-toc-text">一.获取过程</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#ProcessState-self"><span class="post-toc-text">ProcessState::self()</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#ProcessState初始化"><span class="post-toc-text">ProcessState初始化</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#ProcessState-open-driver"><span class="post-toc-text">ProcessState::open_driver()</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#ioctl-fd-BINDER-SET-MAX-THREADS-amp-maxThreads"><span class="post-toc-text">ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads)</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#mmap"><span class="post-toc-text">mmap</span></a></li></ol></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#ProcessState-getContextObject"><span class="post-toc-text">ProcessState::getContextObject()</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#ProcessState-getStrongProxyForHandle"><span class="post-toc-text">ProcessState::getStrongProxyForHandle()</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#ProcessState-lookupHandleLocked"><span class="post-toc-text">ProcessState::lookupHandleLocked()</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#BpBinder-BpBinder"><span class="post-toc-text">BpBinder::BpBinder</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#IPCThreadState-self"><span class="post-toc-text">IPCThreadState::self()</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#IPCThreadState-IPCThreadState"><span class="post-toc-text">IPCThreadState::IPCThreadState()</span></a></li></ol></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#interface-cast"><span class="post-toc-text">interface_cast()</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#IServiceManager-asInterface"><span class="post-toc-text">IServiceManager::asInterface()</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#DECLARE-META-INTERFACE"><span class="post-toc-text">DECLARE_META_INTERFACE</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#IMPLEMENT-META-INTERFACE"><span class="post-toc-text">IMPLEMENT_META_INTERFACE</span></a></li></ol></li></ol></li></ol>
        </nav>
    </aside>
    

<nav id="article-nav">
  
    <a href="/2017/04/28/图解Http二简单的HTTP协议/" id="article-nav-newer" class="article-nav-link-wrap">

      <span class="article-nav-title">
        <i class="fa fa-hand-o-left" aria-hidden="true"></i>
        
          图解Http二简单的HTTP协议
        
      </span>
    </a>
  
  
    <a href="/2017/04/26/Android-Binder技术ServiceManager之服务注册请求的发送/" id="article-nav-older" class="article-nav-link-wrap">
      <span class="article-nav-title">Android-Binder技术ServiceManager之服务注册请求的发送</span>
      <i class="fa fa-hand-o-right" aria-hidden="true"></i>
    </a>
  
</nav>



    
</section>
        
      </div>
      <footer id="footer">
  <div class="outer">
    <div id="footer-info" class="inner">
      
<p>
    <span id="busuanzi_container_site_uv" style='display:none'>
        总访客数：<span id="busuanzi_value_site_uv"></span>
    </span>
    <span id="busuanzi_container_site_pv" style='display:none'>
        总访问量：<span id="busuanzi_value_site_pv"></span>
    </span>
</p>


      <p>
        Powered by  <a href="http://hexo.io/" target="_blank">Hexo</a>
        Theme <a href="//github.com/wongminho/hexo-theme-miho" target="_blank">MiHo</a>
      &copy; 2018 Joker Mei<br>
      </p>
    </div>
  </div>
</footer>
    <script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<script src="//cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
  var mihoConfig = {
      root: "http://mjjde.github.io",
      animate: false,
      isHome: false,
      share: true
  }
</script>
<div class="sidebar">
    <!-- <div id="sidebar-search" title="Search">
        <i class="fa fa-search"></i>
    </div> -->
    <div id="sidebar-category" title="Categories">
        <i class="fa fa-book"></i>
    </div>
    <div id="sidebar-tag" title="Tags">
        <i class="fa fa-tags"></i>
    </div>
    <div id="sidebar-top">
        <span class="sidebar-top-icon"><i class="fa fa-angle-up"></i></span>
    </div>
</div>
<div class="sidebar-menu-box" id="sidebar-menu-box">
    <div class="sidebar-menu-box-container">
        <div id="sidebar-menu-box-categories">
            <a class="category-link" href="/categories/Android技术/">Android技术</a><a class="category-link" href="/categories/其他技术/">其他技术</a><a class="category-link" href="/categories/网络技术/">网络技术</a><a class="category-link" href="/categories/设计模式/">设计模式</a>
        </div>
        <div id="sidebar-menu-box-tags">
            <a href="/tags/Activity/" style="font-size: 10px;">Activity</a> <a href="/tags/Android/" style="font-size: 16px;">Android</a> <a href="/tags/Android-IPC/" style="font-size: 10px;">Android-IPC</a> <a href="/tags/Binder/" style="font-size: 16px;">Binder</a> <a href="/tags/DiskLruCache/" style="font-size: 10px;">DiskLruCache</a> <a href="/tags/Fragment/" style="font-size: 10px;">Fragment</a> <a href="/tags/HTTP/" style="font-size: 20px;">HTTP</a> <a href="/tags/Java/" style="font-size: 10px;">Java</a> <a href="/tags/Notification/" style="font-size: 10px;">Notification</a> <a href="/tags/RemoteView/" style="font-size: 10px;">RemoteView</a> <a href="/tags/Rxjava/" style="font-size: 14px;">Rxjava</a> <a href="/tags/ServiceManager/" style="font-size: 14px;">ServiceManager</a> <a href="/tags/android/" style="font-size: 12px;">android</a> <a href="/tags/gradle/" style="font-size: 10px;">gradle</a> <a href="/tags/java/" style="font-size: 18px;">java</a> <a href="/tags/other/" style="font-size: 10px;">other</a> <a href="/tags/volley/" style="font-size: 12px;">volley</a> <a href="/tags/widget/" style="font-size: 10px;">widget</a> <a href="/tags/事件/" style="font-size: 10px;">事件</a> <a href="/tags/组件化/" style="font-size: 10px;">组件化</a> <a href="/tags/设计模式/" style="font-size: 18px;">设计模式</a>
        </div>
    </div>
    <a href="javascript:;" class="sidebar-menu-box-close">&times;</a>
</div>
<div class="mobile-header-menu-nav" id="mobile-header-menu-nav">
    <div id="mobile-header-menu-container">
        <span class="title">Menu</span>
        <ul class="mobile-header-menu-navbar">
            
            <li>
                <a  href="/">
                    <i class="fa fa-home"></i><span>Home</span>
                </a>
            </li>
            
            <li>
                <a  href="/archives">
                    <i class="fa fa-archive"></i><span>Archives</span>
                </a>
            </li>
            
            <li>
                <a  href="/about">
                    <i class="fa fa-user"></i><span>About</span>
                </a>
            </li>
            
        </ul>
    </div>
</div>
<div class="search-wrap">
    <span class="search-close">&times;</span>
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="back">
            <i class="icon icon-lg icon-chevron-left"></i>
        </a>
        <input class="search-field" placeholder="Search..." id="keywords">
        <a id="search-submit" href="javascript:;">
            <i class="fa fa-search"></i>
        </a>
    <div class="search-container" id="search-container">
        <ul class="search-result" id="search-result">
        </ul>
    </div>
</div>

<div id="search-tpl">
    <li class="search-result-item">
        <a href="{url}" class="search-item-li">
            <span class="search-item-li-title" title="{title}">{title}</span>
        </a>
    </li>
</div>
<script src="/js/search.js"></script>
<script src="/js/main.js"></script>








  </div>
</body>
</html>